Skip to content

fix(trino): pin a session schema for unqualified statements - #721

Merged
cevheri merged 2 commits into
libredb:mainfrom
CunjieLee:fix/trino-session-schema
Sep 9, 2026
Merged

fix(trino): pin a session schema for unqualified statements#721
cevheri merged 2 commits into
libredb:mainfrom
CunjieLee:fix/trino-session-schema

Conversation

@CunjieLee

Copy link
Copy Markdown
Contributor

Description

Add an optional session schema to Trino connections so unqualified statements resolve against the selected catalog and schema.

Before this change, a connection could pin only a catalog, causing statements such as SELECT * FROM widgets and CREATE TABLE t (...) to fail with Schema must be specified when session schema is not set.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Code refactoring
  • Performance improvement
  • Test addition or update

Related Issue

Closes #653

Changes Made

  • Add a Schema field to Trino connection configuration and persist it across creation, editing, seeded connections, and connection identity checks.
  • Send the configured schema through the dialect-derived X-Trino-Schema header while preserving per-query overrides and the existing behavior when no schema is configured.
  • Update the Trino provider documentation, configuration errors, integration tests, component tests, form tests, and browser coverage.

Testing

  • I have tested this locally
  • I have added/updated tests
  • All existing tests pass

The issue was reproduced against a live Trino 476 instance before applying the fix:

  • SELECT * FROM widgets_653 failed because no session schema was set.
  • CREATE TABLE created_653_baseline (...) failed for the same reason.
  • Fully qualified statements continued to succeed.

After applying the fix with Catalog memory and Schema default:

  • The same unqualified SELECT succeeded.
  • The same unqualified CREATE TABLE succeeded.
  • The created table could be queried using its unqualified name.
  • Connections without a schema still omit the schema header.
  • Fully qualified statements continue to work without a configured schema.
  • The schema tree continues to list and qualify tables across the entire catalog.
  • The complete /api/db/query path returns 200 for unqualified statements when a schema is configured and the expected 400 when it is absent.

Validation completed:

  • Full unit, API, integration, hook, security, evaluation, and component test suite
  • All 34 component test groups
  • 46,200/46,200 covered lines (100%)
  • 26 relevant Playwright browser tests
  • Formatting, lint, type checking, Knip, documentation drift, chart drift, channel showcase, and security checks
  • Application build, library build, package type validation, Go formatting, vetting, and tests

Test Environment

  • LibreDB Studio Version: 0.14.1 (3b9a8be)
  • Browser: Playwright Chromium 153.0.8010.12
  • OS: macOS 15.3.2, Apple Silicon arm64
  • Node.js/Bun Version: Node.js 24.20.0 / Bun 1.4.2
  • Database Type: Trino 476 with the memory connector

Screenshots (if applicable)

Not applicable.

Checklist

  • My code follows the project's code style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated the documentation accordingly
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Additional Notes

No dependent changes are required. The fix is compatible with existing Trino connections: an omitted or empty schema continues to send no schema header.

@gitguardian

gitguardian Bot commented Sep 9, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

Since your pull request originates from a forked repository, GitGuardian is not able to associate the secrets uncovered with secret incidents on your GitGuardian dashboard.
Skipping this check run and merging your pull request will create secret incidents on your GitGuardian dashboard.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
36754982 Triggered Generic Password a1cddb5 tests/unit/seed/types.test.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@cevheri

cevheri commented Sep 9, 2026

Copy link
Copy Markdown
Member

Thanks for the patch. One check is red and it is not your code being wrong, so here is what it is and the one-line fix.

GitGuardian Security Checks reports "1 secret uncovered".
The trigger is the only credential-shaped literal in the diff:

tests/unit/seed/types.test.ts:234 : password: "s3cret"

Its generic-password detector matches password: "" without weighing entropy. Because the PR comes from a fork, GitGuardian cannot attach the finding to an incident, so there is no detail page to read behind the check, just the summary.

Two things worth knowing:

  • The check is not in the required set for main (Lint, Typecheck and Build, Unit & Integration Tests, Secret Scan), so it does not
    block a merge.
  • Our own Secret Scan will not flag it. The same literal already sits in several test files and gitleaks' default rules do not report
    it, so no allowlist entry is needed.

Simplest fix: drop the password line from that case. The test asserts SeedConnectionSchema's schema field and the password never reaches an assertion. A placeholder such as "not-a-real-password" works too if you would rather keep the field populated.

Separately, the three required checks have not run yet: fork PRs wait for a maintainer to approve workflows. I will approve them so we get a real signal on the change itself.

@cevheri cevheri left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gitguardian security check

@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@cevheri cevheri added enhancement New feature or request security Supply-chain, auth, or hardening work bug Something isn't working and removed enhancement New feature or request labels Sep 9, 2026
@cevheri

cevheri commented Sep 9, 2026

Copy link
Copy Markdown
Member

The required checks have run now and they are green. The parts of this that were easy to get wrong, you got right: you found every reader of the connection field list including the two that fail nothing at compile time (src/lib/seed/connection-filter.ts and connectionIdentity), you marked schema as "edited" in FIELD_OWNERSHIP so clearing the field genuinely clears it rather than falling back to the stored value, and the header test asserts both arms, which the issue asked for because the negative alone would also pass a build that never sends the header at all.

My earlier request about tests/unit/seed/types.test.ts:234 still stands. While you are in there, five more, all small:

  1. src/lib/db/providers/sql/trino/index.ts:203 still ends "Qualify names in full instead." That is the same copy Trino runs no unqualified statement: the connection pins a catalog and never a schema #653 asked to have re-read, and someone typing USE memory.default is exactly the person who needs to hear the connection now has a Schema field. docs/providers/trino.md:424 quotes it verbatim, so both move together.
  2. docs/SEED_CONNECTIONS.md gained nothing, but you added schema to SeedConnectionSchema and to the filter, and docs/providers/trino.md:494 now claims seeded connections support it. The field table ends at connections[].authSource and the commented example does not mention it. No guard reads that file, so it has to be by hand.
  3. docs/API_DOCS.md:549 is now stale: "a connection is host + port (+ optional database, username)".
  4. docs/API_DOCS.md:1268-1272 lists the fields the server reads and omits schema, while the interface block twelve lines below has it. You classify it as "resolution" yourself in use-connection-payload.ts, so it belongs in that sentence.
  5. src/components/ConnectionModal.tsx:558 has no icon wrapper, so its label sits flush left while "Catalog Name" above it is indented, and it uses font-medium where every neighbouring label uses font-mediumr, a long-standing typo of ours that Tailwind emits nothing for. The new label therefore renders heavier than all its siblings. Match the neighbours for now and I will fix the typo repo-wide separately.

Optional: tests/unit/db/trino/http-transport.test.ts never asserts that a connection-pinned schema alone reaches the header, because both edited cases set options.schema and shadow it. Setting this.schema = undefined leaves all 96 tests in that file green; only the integration file catches it.

Two things I am tracking rather than asking for: with the schema left empty, Create Table and the import modal's new-table path still emit unqualified statements the coordinator refuses, which #653 anticipated under Option 3; and RESOLVABLE_FIELDS does not cover schema, the same as every other engine-specific field.

@CunjieLee

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review. I’ve addressed all requested changes: removed the test password that triggered GitGuardian, updated the Trino session warning and matching documentation, documented the schema field in Seed Connections and the API reference, and aligned the Schema label layout and styling with its neighbors. I also added a direct unit test for the connection-pinned schema header and strengthened the warning assertion. I left the two tracked follow-ups outside this PR as noted. The full test suite, build, and coverage checks pass with 100% line coverage.

@cevheri

cevheri commented Sep 9, 2026

Copy link
Copy Markdown
Member

All six are addressed and I checked each one rather than taking the summary. The three required checks are green.

The optional test you added is the one I care about most, and it is real: setting this.schema = undefined in the constructor turns exactly that test red and leaves the other 96 in the file passing. Same for the warning copy, reverting the sentence in index.ts fails the integration assertion, and both prose copies of it moved together, so the doc cannot drift from the string.

One thing not to chase: GitGuardian will stay red on this branch. It scans commits, not the working tree, and the literal is still in your first commit. The line is gone from seed/types.test.ts, our own Secret Scan is green, the check is not required, and we squash-merge, so nothing reaches main. No history rewrite needed.

One cosmetic leftover I will take myself after merge: in docs/SEED_CONNECTIONS.md the new schema: comment column sits one space right of database: above it. Not worth a push.

Good work on this one. Thanks for the care on the field-list readers and on the test that asserts both arms. I will merge it shortly.

@cevheri
cevheri merged commit f153f8f into libredb:main Sep 9, 2026
21 of 22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working security Supply-chain, auth, or hardening work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Trino runs no unqualified statement: the connection pins a catalog and never a schema

2 participants